package com.m3958.firstgwt.client;

import java.util.Date;
import java.util.List;

import com.google.gwt.core.client.JsArray;
import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.client.Cookies;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.m3958.firstgwt.client.datasource.AssetFolderDataSource;
import com.m3958.firstgwt.client.datasource.RoleDataSource;
import com.m3958.firstgwt.client.datasource.SectionDataSource;
import com.m3958.firstgwt.client.datasource.SiteConfigDataSource;
import com.m3958.firstgwt.client.datasource.UserDataSource;
import com.m3958.firstgwt.client.datasource.XinJianCatDataSource;
import com.m3958.firstgwt.client.layout.PageMistakeLayout;
import com.m3958.firstgwt.client.place.ArticleListPlace;
import com.m3958.firstgwt.client.place.AssetFolderTreePlace;
import com.m3958.firstgwt.client.place.AssetListPlace;
import com.m3958.firstgwt.client.place.DataTemplateListPlace;
import com.m3958.firstgwt.client.place.DiskFileListPlace;
import com.m3958.firstgwt.client.place.FtlListPlace;
import com.m3958.firstgwt.client.place.LinkTreePlace;
import com.m3958.firstgwt.client.place.PageMistakeListPlace;
import com.m3958.firstgwt.client.place.SectionTreePlace;
import com.m3958.firstgwt.client.place.TableSchemaListPlace;
import com.m3958.firstgwt.client.place.UrlStatisticsListPlace;
import com.m3958.firstgwt.client.place.VoteTreePlace;
import com.m3958.firstgwt.client.place.WebSiteEditPlace;
import com.m3958.firstgwt.client.place.XinJianCatTreePlace;
import com.m3958.firstgwt.client.place.XinJianListPlace;
import com.m3958.firstgwt.client.types.ConfigKey;
import com.m3958.firstgwt.client.types.ViewNameEnum;
import com.m3958.firstgwt.client.utils.StringUtils;
import com.m3958.gwtutil.clientside.client.AjaxResult;
import com.m3958.gwtutil.clientside.client.LoginOutService;
import com.m3958.gwtutil.clientside.client.SmartFetchPara;
import com.m3958.gwtutil.clientside.client.YuiWrapper;
import com.m3958.gwtutil.clientside.client.constants.SmartOperationName;
import com.m3958.gwtutil.clientside.client.constants.SmartSubOperationName;
import com.m3958.gwtutil.clientside.client.interfac.IwantAjaxQueenResult;
import com.m3958.gwtutil.clientside.client.jso.SiteConfigJso;
import com.m3958.gwtutil.clientside.client.jso.SmartResponseJsoWrap;
import com.m3958.gwtutil.clientside.client.jso.SmartSuccessResponseJso;
import com.m3958.gwtutil.clientside.client.jso.WebSiteJso;
import com.m3958.gwtutil.clientside.client.utils.HttpAjaxQueen;

//這裡不要注入viewService，不然這個狀態就無法在View裡面使用，會引起循環注入。

@Singleton
public class AppStatus implements IwantAjaxQueenResult{
	
	private DataPanelManager dpm;
	
	private long COOKIE_TIMEOUT = 365 * 24 * 60 * 60 * 1000;
	
	@Inject
	private LoginOutService lios;
	
	private WebSiteJso lastSelectedWebsite;
	
	private MyPlace lastPlace;
	
	public MyPlace getLastPlace() {
		return lastPlace;
	}

	public void setLastPlace(MyPlace lastPlace) {
		this.lastPlace = lastPlace;
	}
	
	@Inject
	private TemporaryRecordAndIdHolder ltr;

	@Inject
	private HttpAjaxQueen ajaxQueen;
	
	@Inject
	private YuiWrapper yui;
	
	private JsArray<SiteConfigJso> clientConfigs;
	
	private String[] editableExts;
	
	//已经登录
	public void start(){
		SmartFetchPara sfp1 = new SmartFetchPara();
		sfp1.putModelName(RoleDataSource.className);
		sfp1.putOpType(SmartOperationName.FETCH.toString());
		sfp1.putSubOpType(SmartSubOperationName.MANY_TO_MANY.toString());
		sfp1.put("_isMaster",false);
		sfp1.putRelationModelName(UserDataSource.className);
		sfp1.putRelationModelId(lios.getLoginedUser().getId() + "");
		sfp1.putUrl("/smartcfud");
		sfp1.putRelationPropertName("roles");
		ajaxQueen.addItem(sfp1, "roles");
		
		SmartFetchPara sfp2 = new SmartFetchPara();
		sfp2.putModelName(SiteConfigDataSource.className);
		sfp2.putOpType(SmartOperationName.FETCH.toString());
		sfp2.put("clientSide", true);
		sfp2.putUrl("/smartcfud");
		ajaxQueen.addItem(sfp2, "siteconfig");
		ajaxQueen.start(AppStatus.this);
		setLastsiteFromCookie();
	}
	
	
	public boolean allowEdit(String fn){
		String ext = StringUtils.getFileExtensionWithDot(fn);
		if(clientConfigs == null)return false;
		if(editableExts == null){
			for(int i=0;i<clientConfigs.length();i++){
				SiteConfigJso scf = clientConfigs.get(i); 
				String ck = scf.getConfigKey();
				if(ck.equals((ConfigKey.ALLOW_EDIT_EXTS.getEname()))){
					String value = clientConfigs.get(i).getConfigValue();
					editableExts = value.split("\\s");
				}
			}
			if(editableExts == null){
				editableExts = new String[]{};
			}
		}
		for(String ex:editableExts){
			if(ex.equalsIgnoreCase(ext)){
				return true;
			}
		}
		return false;
	}

	public void init(JSONObject jo){
		editableExts = null;
	}
	
	private String timeZone;
	
	public String getTimeZone(){
		return timeZone;
	}
	
	public void initTimeZone(){
		timeZone = getTimeZoneNative(); 
	}
	
	private  final native String getTimeZoneNative()/*-{
		var timezone = $wnd.jstz.determine_timezone();
		return timezone.name();
	}-*/;

	public String getSiteId(){
		if(getLastSelectedWebsite() == null){
			return null;
		}else{
			if(getLastSelectedWebsite().getId() == 0 || getLastSelectedWebsite().getId() == -1)return null;
			return getLastSelectedWebsite().getId() + "";
		}
	}

	@Override
	public void onAjaxQueenDataArrival(List<AjaxResult> ars) {
		for(AjaxResult ar : ars){
			SmartResponseJsoWrap rjw = ar.getJsObject().cast();
			SmartSuccessResponseJso rj = rjw.getSmartResponseJso().cast();
			if("siteconfig".equals(ar.getDistinct())){
				clientConfigs = rj.getDataArray().cast();
			}
		}
	}


	public void setDpm(DataPanelManager dpm) {
		this.dpm = dpm;
	}
	
	public DataPanelManager getDpm() {
		return dpm;
	}
	private Long lastMouseMoveTimeStamp;
	
	public void setLastMouseMoveTimeStamp(Long lastMouseMoveTimeStamp) {
		this.lastMouseMoveTimeStamp = lastMouseMoveTimeStamp;
	}

	public Long getLastMouseMoveTimeStamp() {
		return lastMouseMoveTimeStamp;
	}


	public WebSiteJso getLastSelectedWebsite() {
		return lastSelectedWebsite;
	}
	
	private void setLastsiteFromCookie() {
		try {
			String ls = Cookies.getCookie("lastsite");
			if(ls != null){
				ls = URL.decode(ls);
			}
			WebSiteJso ws = yui.jsonParse(ls).cast();
			this.lastSelectedWebsite = ws;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}


	public void setLastSelectedWebsite(WebSiteJso lastSelectedWebsite) {
		try {
			Date expires = new Date((new Date()).getTime() + COOKIE_TIMEOUT);
			Cookies.setCookie("lastsite", URL.encode(yui.jsonStringify(lastSelectedWebsite)),expires);
		} catch (Exception e) {
			e.printStackTrace();
		}
		this.lastSelectedWebsite = lastSelectedWebsite;
	}
	
	public MyPlace getPlaceByLowerCaseName(String s){
		ViewNameEnum vn = ViewNameEnum.NOVIEW;
		try {
			vn = ViewNameEnum.valueOf(s.toUpperCase());
		} catch (Exception e) {}
		
		switch (vn) {
		case SECTION:
			return new SectionTreePlace(getSiteId());
		case ARTICLE:
			return new ArticleListPlace(getSiteId(), ltr.getLastContainerId(SectionDataSource.className));
		case ASSET:
			return new AssetListPlace(getSiteId(), ltr.getLastContainerId(AssetFolderDataSource.className));
		case ASSET_FOLDER:
			return new AssetFolderTreePlace(getSiteId());
		case LINK:
			return new LinkTreePlace(getSiteId());
		case DISKFILE:
			return new DiskFileListPlace(getSiteId());
		case XJ_CAT:
			return new XinJianCatTreePlace(getSiteId());
		case XINJIAN:
			return new XinJianListPlace(getSiteId(),ltr.getLastContainerId(XinJianCatDataSource.className));
		case VOTE:
			return new VoteTreePlace(getSiteId());
		case URL_STATISTICS:
			return new UrlStatisticsListPlace(getSiteId());
		case TABLE_SCHEMA:
			return new TableSchemaListPlace(getSiteId());
		case WEBSITE_EDIT:
			return new WebSiteEditPlace(null);
		case FTL:
			return new FtlListPlace();
		case DATA_TEMPLATE:
			return new DataTemplateListPlace(getSiteId());
		case PAGE_MISTAKE:
			return new PageMistakeListPlace(getSiteId());
		default:
			break;
		}
		return null;
	}
}
